package engine;

import dao.DaoPassageTrainTheorique;
import dao.DaoUtilisateur;
import externaldata.gare.Gare;
import externaldata.passageTrainTheorique.PassageTrainTheorique;
import externaldata.passageTrainTheorique.PassageTrainTheoriqueHelper;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;


public class DailyDatabaseUpdater implements Runnable {
	
	private Object verrou;
	private List<Gare> gares;
	private Date dateProchaineMaj;
	
	public DailyDatabaseUpdater(List<Gare> gares, Object verrou) {
		this.verrou = verrou;
		this.gares = gares;
		
		
		try {
			Date ajd = new Date();
			SimpleDateFormat formatJour = new SimpleDateFormat("dd");
			SimpleDateFormat formatMois = new SimpleDateFormat("MM");
			SimpleDateFormat formatAnnee = new SimpleDateFormat("yyyy");
			
			dateProchaineMaj = new SimpleDateFormat("ddMMyyyyHHmm").parse(
					formatJour.format(ajd) + formatMois.format(ajd) + formatAnnee.format(ajd) + "0300");
			
			// Le prochaine maj devant se faire le lendemain 
			// de la mise en route du serveur :
			Calendar cal = new GregorianCalendar();
			cal.setTime(dateProchaineMaj);
			cal.add(Calendar.DATE, 1);
			
			dateProchaineMaj = cal.getTime();
			
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void run() {
		
		// Première maj
		majPassagesTheoriques();
		
		synchronized (verrou) {
			// La première maj est terminée
			verrou.notify();
		}
		
		while (true) {
			
			try {
				Date ajd = new Date();
				
				// On ajoute un jour à chaque tour de boucle, tant que la date
				// de la prochaine maj est antérieure au moment présent
				while (dateProchaineMaj.getTime() < ajd.getTime()) {
					Calendar cal = new GregorianCalendar();
					cal.setTime(dateProchaineMaj);
					cal.add(Calendar.DATE, 1);
					
					dateProchaineMaj = cal.getTime();
				}
				
				System.out.println(
						"Nombre de minutes avant prochaine maj des passages théoriques : "
						+ (((dateProchaineMaj.getTime() - ajd.getTime()) / 1000) / 60));
				
				// Le thread s'endort jusqu'à la prochaine maj
				Thread.sleep(dateProchaineMaj.getTime() - ajd.getTime());
				
				majPassagesTheoriques();
				
				DaoUtilisateur.updatePointsQuotidien();
				
			} catch (InterruptedException e) {
				// Thread interrompu par la méthode 'interrupt'
				// On termine l'exécution en sortant de la boucle infinie
				break;
			}
		}
	}
	
	private void majPassagesTheoriques() {
		
		System.out.println("Début de la maj des PTT...");
		
		
		// Récupération des nouvelles données
		List<PassageTrainTheorique> passagesTheoriquesAPI = 
				PassageTrainTheoriqueHelper.getProchainsPassages(gares, 1);
		
		List<PassageTrainTheorique> passagesTheoriquesASauvegarder = 
				new ArrayList<PassageTrainTheorique>(passagesTheoriquesAPI);
		
		System.out.println("Nombre de PTT depuis l'API : " + passagesTheoriquesAPI.size());
		
		
		
		// Récupération des anciennes données stockées en BDD
		List<PassageTrainTheorique> passagesTheoriquesBD = 
				DaoPassageTrainTheorique.getAll();
		
		List<PassageTrainTheorique> passagesTheoriquesASuppr = 
				new ArrayList<PassageTrainTheorique>(passagesTheoriquesBD);
		
		System.out.println("Nombre de PTT depuis la BD : " + passagesTheoriquesBD.size());
		
		
		
		// Parcours des listes et comparaisons
		for (PassageTrainTheorique tmp_old_data : passagesTheoriquesBD) {
			
			for (PassageTrainTheorique tmp_new_data : passagesTheoriquesAPI) {
				// Si on a les mêmes data dans la BD et dans le nouveau fichier,
				// alors on peut garder la data en BD sans y toucher
				if (tmp_old_data.equals(tmp_new_data)) {
					passagesTheoriquesASauvegarder.remove(tmp_new_data);
					passagesTheoriquesASuppr.remove(tmp_old_data);
					break;
				}
			}
		}
		
		
		
		// Les datas qui sont restées dans la liste passagesTheoriquesASauvegarder
		// sont les nouvelles données à stocker dans la BD
		System.out.println("Nombre de PTT à sauvegarder en BD : " + passagesTheoriquesASauvegarder.size());
		/*
		for (PassageTrainTheorique ptt : passagesTheoriquesASauvegarder) {
			System.out.println("PTT à sauvegarder : " 
						+ "\n\tNuméro train : " + ptt.getNumeroTrain()
						+ "\n\tNom train : " + ptt.getNomTrain()
						+ "\n\tRéseau : " + ptt.getReseauTrain()
						+ "\n\tGare de passage : " + ptt.getGareDua()
						+ "\n\tArrivée : " + ptt.getArriveeTheorique());
		}
		*/
		
		DaoPassageTrainTheorique.ajouterListe(passagesTheoriquesASauvegarder);
		
		
		
		// Les datas qui sont restées dans la liste passagesTheoriquesASuppr
		// sont les anciennes données à supprimer de la BD
		System.out.println("Nombre de PTT à supprimer de la BD : " + passagesTheoriquesASuppr.size());
		/*
		for (PassageTrainTheorique ptt : passagesTheoriquesASuppr) {
			System.out.println("PTT à supprimer : " 
						+ "\n\tNuméro train : " + ptt.getNumeroTrain()
						+ "\n\tNom train : " + ptt.getNomTrain()
						+ "\n\tRéseau : " + ptt.getReseauTrain()
						+ "\n\tGare de passage : " + ptt.getGareDua()
						+ "\n\tArrivée : " + ptt.getArriveeTheorique());
		}
		*/
		
		DaoPassageTrainTheorique.supprimerListe(passagesTheoriquesASuppr);
		
		
		System.out.println("Fin de la  maj des PTT...");
	}
}
